/**
 *
 * RIP - Routing Information Protocol > baseado na implementação de Kurose-Ross
 *
 * Laboratório de Redes de Computadores Bacharelado em Ciência da Computação -
 * UFSCar, Sorocaba
 *
 * Alunos: Nahim Alves de Souza RA 380059 Rafael Cláudio Domene RA 345040
 *
 * Professora: Yeda Regina Venturini
 *
 */
package nodes;

import rip.*;

public class node0 {

    rtpkt pktRotinaZero = new rtpkt();
    tabelaDistancia distanciaZero = new tabelaDistancia();
    int[] minCost = new int[4];

    public void rtInit0(RIP r) {
        //RIP r = new RIP(); // ERRO!! NAO PODE CRIAR UM RIP() PARA CADA NÓ!!
        distanciaZero.setCusto(0, 0, 0);
        distanciaZero.setCusto(0, 1, 1);
        distanciaZero.setCusto(0, 2, 3);
        distanciaZero.setCusto(0, 3, 7);

        distanciaZero.setCusto(1, 0, 999);
        distanciaZero.setCusto(1, 1, 999);
        distanciaZero.setCusto(1, 2, 999);
        distanciaZero.setCusto(1, 3, 999);

        distanciaZero.setCusto(2, 0, 999);
        distanciaZero.setCusto(2, 1, 999);
        distanciaZero.setCusto(2, 2, 999);
        distanciaZero.setCusto(2, 3, 999);

        distanciaZero.setCusto(3, 0, 999);
        distanciaZero.setCusto(3, 1, 999);
        distanciaZero.setCusto(3, 2, 999);
        distanciaZero.setCusto(3, 3, 999);

        // Seta os caminhos de menor custo no cenario inicial
        minCost[0] = 0;
        minCost[1] = 1;
        minCost[2] = 2;
        minCost[3] = 7;

        // Seta os caminhos de menor custo no cenario inicial no pacote de rotina
        pktRotinaZero.setMinCost(0, minCost[0]);
        pktRotinaZero.setMinCost(1, minCost[1]);
        pktRotinaZero.setMinCost(2, minCost[2]);
        pktRotinaZero.setMinCost(3, minCost[3]);

        pktRotinaZero.setSourceID(0);

        // Envia seus caminhos de menor custo para os nós conectados
        // Para o nó 1
        pktRotinaZero.setDestID(1);
        r.toLayer2(pktRotinaZero);

        // Para o nó 2
        pktRotinaZero.setDestID(2);
        r.toLayer2(pktRotinaZero);

        // Para o nó 3
        pktRotinaZero.setDestID(3);
        r.toLayer2(pktRotinaZero);
        
        System.out.println("\nINIT NODE 0: ");
        this.printdt0(distanciaZero);
                
   
    }

    public void rtUpdate0(rtpkt rcvdpkt, RIP r) {

        int k;
        int auxCusto = 0;
        int vetAuxCusto[] = {0, 0, 0, 0};
        int mudanca = 0;
        //RIP r = new RIP();

        for (k = 0; k < 4; k++) {
            /* Se o custo de caminho do pacote de rotina recebido FOR MENOR
             * que o custo armazenado na tabela de distancia do nó zero para o nó o qual
             * enviou esse pacote( SourceID ), então a tabela de distancias do nó zero é atualizada
             * com o custo de caminho do pacote de rotina recebido
             */
            if (rcvdpkt.getMinCost(k) < distanciaZero.getCusto(rcvdpkt.getSourceID(), k)) {
                distanciaZero.setCusto(rcvdpkt.getSourceID(), k, rcvdpkt.getMinCost(k));
            }
        }

        /* Verificando o caminho de menor custo do nó zero para os demais nós
         * pois a tabela de distancias foi atualizada acima através do pacotes de
         * rotina recebido
         */

        // Verifica o menor caminho entre o nó 0 e nó 1
        auxCusto = Math.min(distanciaZero.getCusto(0, 1), distanciaZero.getCusto(0, 2) + distanciaZero.getCusto(2, 1));
        auxCusto = Math.min(auxCusto, distanciaZero.getCusto(0, 3) + distanciaZero.getCusto(3, 2) + distanciaZero.getCusto(2, 1));
        vetAuxCusto[1] = auxCusto;

        // Verifica o menor caminho entre o nó 0 e nó 2
        auxCusto = Math.min(distanciaZero.getCusto(0, 2), distanciaZero.getCusto(0, 1) + distanciaZero.getCusto(1, 2));
        auxCusto = Math.min(auxCusto, distanciaZero.getCusto(0, 3) + distanciaZero.getCusto(3, 2));
        vetAuxCusto[2] = auxCusto;

        // Verifica o menor caminho entre o nó 0 e nó 3
        auxCusto = Math.min(distanciaZero.getCusto(0, 3), distanciaZero.getCusto(0, 2) + distanciaZero.getCusto(2, 3));
        auxCusto = Math.min(auxCusto, distanciaZero.getCusto(0, 1) + distanciaZero.getCusto(1, 2) + distanciaZero.getCusto(2, 3));
        vetAuxCusto[3] = auxCusto;

        /* Verificamos se as distancias armazenadas no vetor vetAuxCusto são menores
         * que as atualmente armazenadas na tabela de distancias do nó zero
         */
        for (k = 0; k < 4; k++) {
            /* Se o custo de caminho armazenado no vetAuxCusto FOR MENOR
             * que o custo armazenado na tabela de distancia do nó zero, então
             * a tabela de distancias do nó zero é atualizada com o custo de
             * caminho armazenado em vetAuxCusto
             */
            if (vetAuxCusto[k] < distanciaZero.getCusto(0, k)) {
                distanciaZero.setCusto(0, k, rcvdpkt.getMinCost(k));
                mudanca = 1;
            }
        }


        // Se houve mudanca então envia um pacote de rotina para os nós adjacentes
        if (mudanca == 1) {
            // Para o nó 1
            pktRotinaZero.setDestID(1);
            r.toLayer2(pktRotinaZero);

            // Para o nó 2
            pktRotinaZero.setDestID(2);
            r.toLayer2(pktRotinaZero);

            // Para o nó 3
            pktRotinaZero.setDestID(3);
            r.toLayer2(pktRotinaZero);
        }

        
        System.out.println("\nUPDATE NODE 0: ");
        this.printdt0(distanciaZero);

    }

    public void printdt0(tabelaDistancia dtptr) {

        System.out.println("                via     ");
        System.out.println("   D0 |    1     2    3 ");
        System.out.println("  ----|-----------------");
        System.out.println("     1|  " + dtptr.getCusto(1, 1) + "  " + dtptr.getCusto(1, 2) + "  " + dtptr.getCusto(1, 3));
        System.out.println("dest 2|  " + dtptr.getCusto(2, 1) + "  " + dtptr.getCusto(2, 2) + "  " + dtptr.getCusto(2, 3));
        System.out.println("     3|  " + dtptr.getCusto(3, 1) + "  " + dtptr.getCusto(3, 2) + "  " + dtptr.getCusto(3, 3));

    }

    public void linkHandler0(int destino, int novoCusto) {
        minCost[destino] = novoCusto;
    }
}
